<?php

namespace App\Http\Controllers\Home;

use App\Constants\ResponseCode;
use App\Models\Article;
use App\Models\Category;
use App\Models\Links;
use App\Models\Setting;
use App\Models\Tags;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Cache;
use function env;
use function request;
use function view;

class CommonController extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    protected $require = [];
    protected $validate = [];
    protected $selectable = [];
    protected $data = [];
    protected $code = '';
    protected $error = '';
    protected $getArticle = false;

    public function __construct()
    {
        $cate_id = request('cate_id', 0);
        $tags_id = request('tags_id', 0);
        $article_list = $hot_article = [];
        if ($this->getArticle){
            // 获取文章数据信息
            $article_model = new Article();
            $article_list = $article_model->articleList($cate_id, $tags_id, true);
            $hot_article = $article_model->articleList();
        }
        // 获取友情链接信息
        $links_model = new Links();
        $links_list = $links_model->getList();
        // 获取标签信息
        $tags_model = new Tags();
        $tags_list = $tags_model->getList([['looks', '>', 0]]);
        // 获取标签名称
        $tags_name = $tags_model->getField($tags_id, 'name');
        // 获取分类名称
        $category_model = new Category();
        $category_list = $category_model->getList();
        $cate_name = $category_model->getField($cate_id, 'name');
        // 获取站点数据
        $setting_model = new Setting();
        $site_data = $setting_model->settingFind('site');

        view()->share([
            'cate_id'=>$cate_id,
            'tags_id'=>$tags_id,
            'article_list'=>$article_list,
            'hot_article'=>$hot_article,
            'category_list'=>$category_list,
            'links_list'=>$links_list,
            'tags_list'=>$tags_list,
            'tags_name'=>$tags_name,
            'cate_name'=>$cate_name,
            'site_data'=>$site_data
        ]);
    }

    /**
     * 验证请求参数
     * @param $param
     * @param $request
     * @return bool
     */
    protected function verifyParam($param = [], $request = 'post')
    {
        if ($request == 'post'){
            $post_data = request()->post();
        }else{
            $post_data = request()->all();
        }
        if (!empty($param)){
            $this->require = $param;
        }
        if (!empty($this->require)){
            if (is_string($this->require)){
                $this->require = explode(',', $this->require);
            }
        }
        if (!empty($this->selectable)){
            if (is_string($this->selectable)){
                $this->selectable = explode(',', $this->selectable);
            }
        }
        if (!empty($this->require) || !empty($this->selectable)){
            if (empty($this->selectable)){
                $param = $this->require;
            }else{
                $param = array_merge($this->require, $this->selectable);
            }
            $array_keys = array_keys($post_data);
            foreach ($array_keys as $key) {
                if (!in_array($key, $param)){
                    unset($post_data[$key]);
                }
            }
            if (!empty($this->require)){
                foreach ($this->require as $val){
                    if (!isset($post_data[$val]) || $post_data[$val] === ''){
                        if (!empty($this->validate[$val])){
                            $this->error = $this->validate[$val];
                        }else{
                            $this->error = '缺少请求参数：' . $val;
                        }
                        $this->code = ResponseCode::PARAM_ERR;
                        return false;
                    }
                }
            }
            $this->data = $post_data;
            // 是否保存记录参数信息
            if (env('APP_DEBUG')){
                $this->consoleLog($this->data);
            }
        }
        return true;
    }

    /**
     * 验证请求头
     * @param $require
     * @return bool
     */
    protected function verifyToken($require = true)
    {
        $auth_token = request()->header('Authorization');
        if (empty($auth_token)){
            if ($require){
                $this->error = '缺少请求头Authorization';
                $this->code = ResponseCode::UNAUTH;
                return false;
            }
        }
        $user_token = new UserToken();
        $result = $user_token->tokenAuth(md5($auth_token));
        if (empty($result->user_id)){
            if ($require){
                $this->error = '系统检测到您长时间未登陆，请重新登录';
                $this->code = ResponseCode::UNAUTH;
                return false;
            }
        }else{
            // 获取用户信息
            $user_model = new User();
            $user_fields = 'id,phone,openid,invite_id,status,third_check,created_at,updated_at';
            $user_data = $user_model->getFind($result->user_id, $user_fields);
            if (empty($user_data)){
                if ($require) {
                    $this->error = '系统检测到您长时间未登陆，请重新登录';
                    $this->code = ResponseCode::UNAUTH;
                    return false;
                }
            }else{
                // 更新在线时间10分钟
                if (empty($user_data->updated_at) || strtotime($user_data->updated_at) < time() - 3600){
                    // 更新在线时间
                    $user_model->where('id', '=', $user_data->id)->update([
                        'updated_at'=>date('Y-m-d H:i:s', time())
                    ]);
                }
                $this->data['user_id'] = $user_data->id;
                $this->userId = $user_data->id;
                $this->userData = $user_data;
            }
        }
        return true;
    }

    /**
     * 验证账户是否正常
     * @return bool
     */
    protected function verifyAccount($target_id = 0)
    {
        if (!empty($target_id)){
            $user_id = $target_id;
            $user_model = new User();
            $user_fields = 'id,phone,openid,invite_id,status,third_check,created_at,updated_at';
            $userData = $user_model->getFind($user_id, $user_fields);
        }else{
            $user_id = $this->userId;
            $userData = $this->userData;
        }
        // 验证账户是否认证
        $cert_model = new Certification();
        if (!$cert_model->getExists(['user_id'=>$user_id])){
            if ($target_id){
                $this->error = '对方账户未进行实名认证';
            }else{
                $this->error = '请先进行实名认证';
            }
            $this->code = 2004;
            return false;
        }
        if (empty($userData->openid)){
            if ($target_id){
                $this->error = '对方账户未进行微信授权';
            }else{
                $this->error = '请先进行微信授权';
            }
            $this->code = 2004;
            return false;
        }
        if (!$userData->third_check){
            if ($target_id){
                $this->error = '对方账户未进行三方认证';
            }else{
                $this->error = '请先三方认证';
            }
            $this->code = 2004;
            return false;
        }
        if ($userData->status == 1){
            if ($target_id){
                $this->error = '该账户已被冻结';
            }else{
                $this->error = '您的账户已被冻结';
            }
            $this->code = ResponseCode::UNAUTH;
            return false;
        }
        return true;
    }

    /**
     * 验证请求频繁
     * @param int $user_id
     * @param int $timeout
     * @return bool
     */
    protected function verifyRequest($user_id = 0, int $timeout = 5)
    {
        if (!$user_id){
            $user_id = $this->userId;
        }
        $limit_key = 'limit_request_'.$user_id;
        $ip = $_SERVER['HTTP_ALI_CDN_REAL_IP'] ?? request()->ip();
        $limit_ip_key = 'limit_ip_'.$ip;
        $limit_account_key = 'limit_account_'.$user_id;
        $limit = Cache::get($limit_key);
        $limit_ip = Cache::get($limit_ip_key);
        $limit_account= Cache::get($limit_account_key);
        if($limit_account > 10){
            $this->error = '操作频繁，请稍后再试';
            $this->code = ResponseCode::FORBIDDEN;
            return false;
        }
        if($limit_account) {
            Cache::add($limit_account_key, $limit_account + 1, $timeout);
        }else {
            Cache::add($limit_account_key,1, $timeout);
        }
        if($limit){
            $this->error = '操作频繁，请稍后再试';
            $this->code = ResponseCode::FORBIDDEN;
            return false;
        }else {
            Cache::add($limit_key, $ip, $timeout);
        }
        if($limit_ip){
            $this->error = '操作频繁，请稍后再试';
            $this->code = ResponseCode::FORBIDDEN;
            return false;
        }else{
            Cache::add($limit_ip_key, $user_id, $timeout);
        }
        return true;
    }

    /**
     * 验证失败信息
     * @return \Illuminate\Http\JsonResponse
     */
    protected function verifyError()
    {
        return $this->jsonError($this->error, $this->code);
    }

    /**
     * @param int $code
     * @param array $data
     * @param string $message
     */
    protected function jsonReturn($code = 0, $data = [], $message = '')
    {
        $result = [
            'code' => $code,
            'data' => $data,
            'message'  => $message,
        ];
        return response()->json($result);
    }

    /**
     * 获取数据成功；肯定有数据返回对象数组形式
     * @param array $data
     * @param string $message
     */
    protected function jsonResult($data = [], $message = '')
    {
        return $this->jsonReturn(ResponseCode::SUCCESS, $data, $message);
    }

    /**
     * 操作成功
     * @param string $message
     * @param array $data
     */
    protected function jsonSuccess($message = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::SUCCESS, (object)$data, $message);
    }

    /**
     * 操作失败
     * @param string $message
     * @param array $data
     */
    protected function jsonError($message = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::ERROR, (object)$data, $message);
    }

    /**
     * 数据日志保存
     * @param $data
     * @param $type
     * @param int $flags
     */
    protected function consoleLog($data, $type = '', $flags = FILE_APPEND)
    {
        $dir = getcwd() . '/api_log/';
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        $html = '';
        if (is_array($data)) $data = json_encode($data);
        $filename = $dir . $type . date('YmdH') . '.html';
        if (!file_exists($filename)) {
            $html .= '<!DOCTYPE html><html><head>';
            $html .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
            $html .= '</head><body>';
        }
        $html .= '<div style="display: inline-block;margin-left: 35%">';
        $html .= '<h5 style="margin: 5px 0">---------------------------------------------------------------</h5>';
        $html .= '<h5 style="margin: 5px 0">执行日期：' . date('Y-m-d H:i:s', time()) . '</h5>';
        $html .= '<h5 style="margin: 5px 0">请求地址：<textarea style="display: inline-block;width: 100%;border: none;font-size: 14px;font-weight: bold;font-family: bold;">' . request()->url() . '</textarea></h5>';
        $html .= '<h5 style="margin: 5px 0">数据信息：<textarea style="display: inline-block;width: 100%;border: none;font-size: 14px;font-weight: bold;font-family: bold;">' . $data . '</textarea></h5>';
        $html .= '</div>';
        if (!file_exists($filename)) {
            $html .= '</body></html>';
        }
        file_put_contents($filename, $html, $flags);
    }

}
